package model.strategys;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import javax.swing.JOptionPane;

import view.MainAuxiliar;

import model.cubos.Adesivo;
import model.cubos.Cor;
import model.cubos.CuboMagico;
import model.cubos.CuboMagico3x3x3;
import model.rotations.RotationsImpl;

/**
 * @author
 * Classe que contém o algoritmo básico de resolução do cubo
 */
public class AlgoritmoBasico implements MyStrategys {
        
        private CuboMagico3x3x3 cubo;
        private int passo;
        private Collection movs = new ArrayList();
        private String mensagem = "";
        private Adesivo origem;
        private Adesivo destino;
        private Adesivo origemDois;
        private Adesivo destinoDois;
        private final RotationsImpl rotacao = new RotationsImpl();
        
        
        public AlgoritmoBasico(){
        }
        
        @Override
        public void resolver(CuboMagico cubo) {
                setCubo((CuboMagico3x3x3) cubo);
                resolveMeioSuperior();
        }
        

        /** Método que retorna os movimentos necessários para resolução da etapa Cruz Branca do 
         * Cubo à partir de uma configuração recebida juntamente com a explicação necessária
         */
        public  void resolveCruz(){
                movs.clear();

                String aux = "";
                int i = 0;
                
                Adesivo[][][] matriz = cubo.getCubo();
                int flag = 0;
                
                /*
                 * posicionar o amarelo na face superior
                 */
                
                setDestino(matriz[4][1][1]);
                while(!matriz[4][1][1].isCor(Cor.AMARELO)){
                        if(matriz[1][1][1].isCor(Cor.AMARELO) || matriz[5][1][1].isCor(Cor.AMARELO) || 
                                matriz[3][1][1].isCor(Cor.AMARELO)){
                                rotacao.Z(cubo);
                        }
                        if(matriz[0][1][1].isCor(Cor.AMARELO) || matriz[2][1][1].isCor(Cor.AMARELO)){
                                rotacao.X(cubo);
                        }
                }               
                
                setDestino(matriz[0][1][1]);
                while(!matriz[0][1][1].isCor(Cor.AZUL)){//enquanto não houver quadrado branco na posi��o [0][0][1]
                        rotacao.Y(cubo);
                }
                
                if(matriz[0][2][1].isCor(Cor.AZUL) &&  matriz[0][1][1].isCor(Cor.AZUL) && matriz[5][0][1].isCor(Cor.BRANCO) && matriz[5][1][1].isCor(Cor.BRANCO) &&
                                (matriz[1][2][1].isCor(Cor.VERMELHO) && matriz[1][1][1].isCor(Cor.VERMELHO) && matriz[5][1][2].isCor(Cor.BRANCO) && matriz[5][1][1].isCor(Cor.BRANCO)) &&
                                (matriz[2][2][1].isCor(Cor.VERDE) && matriz[2][1][1].isCor(Cor.VERDE) && matriz[5][2][1].isCor(Cor.BRANCO) && matriz[5][1][1].isCor(Cor.BRANCO) ) &&
                                (matriz[3][2][1].isCor(Cor.LARANJA) && matriz[3][1][1].isCor(Cor.LARANJA) && matriz[5][1][0].isCor(Cor.BRANCO) && matriz[5][1][1].isCor(Cor.BRANCO))){
                        return;
                }
                
                // não estiver pronto
                while( flag != 1){//testar se passo está completo - 1 e 2
                        //etapa 3
                        if(matriz[0][0][1].isCor(Cor.BRANCO) || //se existir branco em uma dessas posições
                                        matriz[1][0][1].isCor(Cor.BRANCO) ||
                                        matriz[2][0][1].isCor(Cor.BRANCO) ||
                                        matriz[3][0][1].isCor(Cor.BRANCO)){
                                                        
                                aux = new String();
                                mensagem = new String();
                                setDestino(matriz[0][0][1]);
                                
                                while(!matriz[0][0][1].isCor(Cor.BRANCO)){//enquanto não houver quadrado branco na posi��o [0][0][1]
                                        rotacao.U(cubo);
                                }
                                
                                setDestino(matriz[0][1][2]);
                                
                                rotacao.F(cubo);
                                
                                setDestino(matriz[4][1][2]);
                                
                                while(matriz[4][1][2].isCor(Cor.BRANCO)){//enquanto existir quadrado branco na posi��o [4][1][2]
                                        rotacao.U(cubo);//movimento U
                                }
                                
                                setDestino(matriz[4][1][2]);
                                
                                rotacao.R(cubo);//movimento R
                        }
                        //fim da etapa 3
                        //***************
                        //etapa 4
                        else //se não existir quadrado branco em nenhuma das posições [0][0][1], [1][0][1], [2][0][1], [3][0][1] 
                                if(matriz[0][1][0].isCor(Cor.BRANCO) || //verificar se existe quadrado branco nessas posições
                                                matriz[1][1][0].isCor(Cor.BRANCO) ||
                                                matriz[2][1][0].isCor(Cor.BRANCO) ||
                                                matriz[3][1][0].isCor(Cor.BRANCO)  ){
                                        setDestino(matriz[0][1][0]);
                                        
                                        while(!matriz[0][1][0].isCor(Cor.BRANCO)){//enquanto não existir quadrado branco nessas posições
                                                rotacao.Y(cubo);//movimento Y
                                        }
                                        
                                        setDestino(matriz[4][1][0]);
                                        
                                        while(matriz[4][1][0].isCor(Cor.BRANCO)){//enquanto existir quadrado branco nessas posições
                                                rotacao.U(cubo);//movimento U
                                        }       
                                        
                                        setDestino(matriz[4][1][0]);
                                        
                                        rotacao.L_(cubo);//movimento L'
                                }
                        //fim da ETAPA 4
                        //**********************
                        //etapa 5
                                else
                                        if(matriz[0][1][2].isCor(Cor.BRANCO) ||//verificar se existe quadrado branco nessas posições
                                                        matriz[1][1][2].isCor(Cor.BRANCO) ||
                                                        matriz[2][1][2].isCor(Cor.BRANCO) ||
                                                        matriz[3][1][2].isCor(Cor.BRANCO)){
                                                
                                                setDestino(matriz[3][1][2]);
                                                
                                                while(!matriz[3][1][2].isCor(Cor.BRANCO)){//enquanto não existir quadrados brancos nessas posições
                                                        rotacao.Y(cubo);//movimento Y
                                                }
                                                
                                                if(matriz[4][2][1].isCor(Cor.BRANCO)){//verificar se existe quadrado branco nessas posições
                                                        
                                                        setDestino(matriz[4][2][1]);
                                                        
                                                        while(matriz[4][2][1].isCor(Cor.BRANCO)){//enquanto existir quadrado branco nessas posições
                                                                rotacao.U(cubo);//movimento U
                                                        }
                                                }
                                                setDestino(matriz[4][2][1]);
                                                
                                                rotacao.F(cubo);//movimento F
                                        }
                        
                        //fim da etapa 5
                        //********************
                        //etapa 7
                                        else
                                                if(matriz[5][0][1].isCor(Cor.BRANCO) ||//verificar se existe quadrado branco nessas posições
                                                                matriz[5][1][0].isCor(Cor.BRANCO) ||
                                                                matriz[5][1][2].isCor(Cor.BRANCO) ||
                                                                matriz[5][2][1].isCor(Cor.BRANCO)){
                                                        
                                                        setDestino(matriz[5][0][1]);
                                                        
                                                        while(!matriz[5][0][1].isCor(Cor.BRANCO)){
                                                                rotacao.D(cubo);//movimento D
                                                        }
                                                        
                                                        if(matriz[4][2][1].isCor(Cor.BRANCO)){//verificar se existe quadrado branco nessas posições
                                                                
                                                                setDestino(matriz[4][2][1]);
                                                                
                                                                while(matriz[4][2][1].isCor(Cor.BRANCO)){//enquanto existir quadrado branco nessas posições
                                                                        rotacao.U(cubo);//movimento U
                                                                }
                                                                
                                                        }
                                                        
                                                        setDestino(matriz[4][2][1]);
                                                        
//                                                      realizar movimento F2
                                                        rotacao.F(cubo);//movimento F
                                                        rotacao.F(cubo);//movimento F
                                                        
                                                        //fim do movimento F2
                                                        
                                                }
                        //fim da etapa 7
                        //*********************
                        //etapa 8
                                                else
                                                        if(matriz[0][2][1].isCor(Cor.BRANCO) ||//verificar se existe quadrado branco nessas posições
                                                                        matriz[1][2][1].isCor(Cor.BRANCO) ||
                                                                        matriz[2][2][1].isCor(Cor.BRANCO) ||
                                                                        matriz[3][2][1].isCor(Cor.BRANCO)){
                                                                setDestino(matriz[0][2][1]);
                                                                
                                                                while(!matriz[0][2][1].isCor(Cor.BRANCO)){
                                                                        rotacao.D(cubo);//movimento D   
                                                                }
                                                                
                                                                setDestino(matriz[4][2][1]);
                                                                
                                                                while(matriz[4][2][1].isCor(Cor.BRANCO)){
                                                                        rotacao.U(cubo);//movimento U
                                                                }
                                                                
                                                                rotacao.F(cubo);//movimento F
                                                        }
                        //fim da etapa 8
                        //*************
                        //etapa 9
                        if((matriz[4][0][1].isCor(Cor.BRANCO)) &&//verificar se existe quadrado branco nessas posições
                                        (matriz[4][1][0].isCor(Cor.BRANCO)) &&
                                        (matriz[4][1][2].isCor(Cor.BRANCO)) &&
                                        (matriz[4][2][1].isCor(Cor.BRANCO)) ){
                                
                                for(int j = 0; j < 4; j++){
                                        setDestino(matriz[0][1][1]);
                                        
                                        switch(matriz[0][1][1].getKey()){
                                        case 4:
                                                while(!(matriz[0][0][1].isCor(Cor.AZUL) && matriz[4][2][1].isCor(Cor.BRANCO) )){
                                                        rotacao.U(cubo);//movimento U
                                                }
//                                              realizar movimento F2
                                                
                                                rotacao.F(cubo);//movimento F
                                                rotacao.F(cubo);//movimento F
                                                break;
                                                
                                        case 13:
                                                while(!(matriz[0][0][1].isCor(Cor.VERMELHO) && matriz[4][2][1].isCor(Cor.BRANCO))){
                                                        rotacao.U(cubo);//movimento U
                                                }
                                                
//                                              realizar movimento F2
                                                
                                                rotacao.F(cubo);//movimento F
                                                rotacao.F(cubo);//movimento F
                                                break;
                                                
                                        case 22:
                                                while(!(matriz[0][0][1].isCor(Cor.VERDE) && matriz[4][2][1].isCor(Cor.BRANCO))){
                                                        rotacao.U(cubo);//movimento U
                                                }
//                                              realizar movimento F2
                                                
                                                rotacao.F(cubo);//movimento F
                                                rotacao.F(cubo);//movimento F
                                                break;
                                                
                                        case 31:
                                                while(!(matriz[0][0][1].isCor(Cor.LARANJA) && matriz[4][2][1].isCor(Cor.BRANCO))){
                                                        rotacao.U(cubo);//movimento U
                                                }
                                                
//                                              realizar movimento F2
                                                rotacao.F(cubo);//movimento F
                                                rotacao.F(cubo);//movimento F
                                        }
                                        rotacao.Y(cubo);//movimento Y
                                }
                        }
                        setDestino(matriz[0][1][1]);
                        
                        while(!matriz[0][1][1].isCor(Cor.AZUL)){
                                rotacao.Y(cubo);
                        }
                        
                        if((matriz[0][2][1].isCor(Cor.AZUL) &&  matriz[0][1][1].isCor(Cor.AZUL) && matriz[5][0][1].isCor(Cor.BRANCO) && matriz[5][1][1].isCor(Cor.BRANCO)) &&
                                        (matriz[1][2][1].isCor(Cor.VERMELHO) && matriz[1][1][1].isCor(Cor.VERMELHO) && matriz[5][1][2].isCor(Cor.BRANCO) && matriz[5][1][1].isCor(Cor.BRANCO)) &&
                                        (matriz[2][2][1].isCor(Cor.VERDE) && matriz[2][1][1].isCor(Cor.VERDE) && matriz[5][2][1].isCor(Cor.BRANCO) && matriz[5][1][1].isCor(Cor.BRANCO)) &&
                                        (matriz[3][2][1].isCor(Cor.LARANJA) && matriz[3][1][1].isCor(Cor.LARANJA) && matriz[5][1][0].isCor(Cor.BRANCO) && matriz[5][1][1].isCor(Cor.BRANCO))){
                                
                                flag = 1;
                        }
                        
                        
                }
                return;
        }
        
        /** Método que retorna os movimentos necessários para resolução da etapa Canto Inferior do 
         * Cubo à partir de uma configuração recebida juntamente com a explicação necessária
         */
        
        public  void resolveCantoInferior(){
                resolveCruz();
                Adesivo[][][] matriz = cubo.getCubo();
                int flag = 0;
                int j = 0;
                if(matriz[5][0][0].getKey() == 45 && matriz[5][0][2].getKey() == 47 && matriz[5][2][0].getKey() == 51 && matriz[5][2][2].getKey() == 53)
                        flag = 1;
                
                while(flag != 1){
                        
                        //etapa1
                        
                        if( matriz[0][0][0].isCor(Cor.BRANCO) |//(matriz[0][0][0].getKey() >= 45 && matriz[0][0][0].getKey() <= 53)  |
                                        (matriz[1][0][0].isCor(Cor.BRANCO) ) |//matriz[1][0][0].getKey() >= 45 && matriz[1][0][0].getKey() <= 53) |
                                        (matriz[2][0][0].isCor(Cor.BRANCO) ) |//[2][0][0].getKey() >= 45 && matriz[2][0][0].getKey() <= 53) |
                                        (matriz[3][0][0].isCor(Cor.BRANCO) ) ){ //matriz[3][0][0].getKey() >= 45 && matriz[3][0][0].getKey() <= 53) ){
                                
                                setDestino(matriz[1][0][0]);
                                
                                while(!matriz[1][0][0].isCor(Cor.BRANCO) ){//matriz[1][0][0].getKey() < 45){//enquanto não existir quadrado brano na posi��o [1][0][0]
                                        rotacao.U(cubo);
                                }
                                
                                setDestino(matriz[0][0][2]);
                                
                                if(matriz[0][0][2].isCor(Cor.AZUL)){//matriz[0][0][2].getKey() >= 0 && matriz[0][0][2].getKey() <= 8){
                                        
                                        setDestino(matriz[0][1][1]);
                                        
                                        while(!matriz[0][1][1].isCor(Cor.AZUL)){//matriz[0][1][1].getKey() != 4){//enquanto não existir peça azul
                                                rotacao.E(cubo);
                                                rotacao.D(cubo);        
                                        }
                                        setDestino(matriz[0][2][2]);
                                        
                                        rotacao.R(cubo);
                                        rotacao.U(cubo);
                                        rotacao.R_(cubo);
                                }
                                else if(matriz[0][0][2].isCor(Cor.VERMELHO)){//matriz[0][0][2].getKey() >= 9 && matriz[0][0][2].getKey() <= 17){
                                        
                                        setDestino(matriz[0][1][1]);
                                        
                                        while(!matriz[0][1][1].isCor(Cor.VERMELHO)){//matriz[0][1][1].getKey() != 13){ enquanto não for vermelho
                                                rotacao.E(cubo);
                                                rotacao.D(cubo);
                                        }
                                        setDestino(matriz[0][2][2]);
                                        
                                        rotacao.R(cubo);
                                        rotacao.U(cubo);
                                        rotacao.R_(cubo);
                                }
                                
                                else if(matriz[0][0][2].isCor(Cor.VERDE)){//matriz[0][0][2].getKey() >= 18 && matriz[0][0][2].getKey() <= 26){
                                        
                                        setDestino(matriz[0][1][1]);
                                        
                                        while(!matriz[0][1][1].isCor(Cor.VERDE)){//matriz[0][1][1].getKey() != 22){ enquanto não for verde
                                                rotacao.E(cubo);
                                                rotacao.D(cubo);        
                                        }
                                        setDestino(matriz[0][2][2]);
                                        
                                        rotacao.R(cubo);
                                        rotacao.U(cubo);
                                        rotacao.R_(cubo);
                                }
                                
                                else if(matriz[0][0][2].isCor(Cor.LARANJA)){//matriz[0][0][2].getKey() >= 27 && matriz[0][0][2].getKey() <= 35 ){
                                        setDestino(matriz[0][1][1]);
                                        
                                        while(!matriz[0][1][1].isCor(Cor.LARANJA)){//matriz[0][1][1].getKey() != 31){ enquanto não for laranja
                                                rotacao.E(cubo);
                                                rotacao.D(cubo);        
                                        }
                                        
                                        setDestino(matriz[0][2][2]);
                                        
                                        rotacao.R(cubo);
                                        rotacao.U(cubo);
                                        rotacao.R_(cubo);
                                }
                                
                        }
                        //fim da etapa 1
                        //**************
                        //etapa 2
                        else if( matriz[0][0][2].isCor(Cor.BRANCO) |//(matriz[0][0][2].getKey() >= 45 && matriz[0][0][2].getKey() <= 53) |
                                        (matriz[1][0][2].isCor(Cor.BRANCO) )|//matriz[1][0][2].getKey() >= 45 && matriz[1][0][2].getKey() <= 53) |
                                        (matriz[2][0][2].isCor(Cor.BRANCO) )|//matriz[2][0][2].getKey() >= 45 && matriz[2][0][2].getKey() <= 53) |
                                        (matriz[3][0][2].isCor(Cor.BRANCO) ) ) {//matriz[3][0][2].getKey() >= 45 && matriz[3][0][2].getKey() <= 53) ){
                                setDestino(matriz[3][0][2]);
                                
                                while(!matriz[3][0][2].isCor(Cor.BRANCO) ){//matriz[3][0][2].getKey() < 45){enquanto não for branca
                                        rotacao.U(cubo);
                                }
                                
                                setDestino(matriz[0][0][0]);
                                if( matriz[0][0][0].isCor(Cor.AZUL) ){//matriz[0][0][0].getKey() >= 0 && matriz[0][0][0].getKey() <= 8){
                                        setDestino(matriz[0][1][1]);
                                        
                                        while(!matriz[0][1][1].isCor(Cor.AZUL) ){//matriz[0][1][1].getKey() != 4){ enquanto não for azul
                                                rotacao.E(cubo);
                                                rotacao.D(cubo);        
                                        }
                                        
                                        setDestino(matriz[0][2][0]);
                                        
                                        rotacao.L_(cubo);
                                        rotacao.U_(cubo);
                                        rotacao.L(cubo);
                                }
                                else if(matriz[0][0][0].isCor(Cor.VERMELHO) ){//matriz[0][0][0].getKey() >= 9 && matriz[0][0][0].getKey() <= 17){
                                        setDestino(matriz[0][1][1]);
                                        
                                        while(!matriz[0][1][1].isCor(Cor.VERMELHO) ){//matriz[0][1][1].getKey() != 13){ //enquanto não for vermelho
                                                rotacao.E(cubo);
                                                rotacao.D(cubo);
                                        }
                                        setDestino(matriz[0][2][0]);
                                        
                                        rotacao.L_(cubo);
                                        rotacao.U_(cubo);
                                        rotacao.L(cubo);
                                }
                                
                                else if(matriz[0][0][0].isCor(Cor.VERDE) ){//matriz[0][0][0].getKey() >= 18 && matriz[0][0][0].getKey() <= 26){
                                        setDestino(matriz[0][1][1]);
                                        
                                        while(!matriz[0][1][1].isCor(Cor.VERDE) ){//matriz[0][1][1].getKey() != 22){ //
                                                rotacao.E(cubo);
                                                rotacao.D(cubo);        
                                        }
                                        setDestino(matriz[0][2][0]);
                                        
                                        rotacao.L_(cubo);
                                        rotacao.U_(cubo);
                                        rotacao.L(cubo);
                                }
                                
                                else if(matriz[0][0][0].isCor(Cor.LARANJA) ){//matriz[0][0][0].getKey() >= 27 && matriz[0][0][0].getKey() <= 35){
                                        setDestino(matriz[0][1][1]);
                                        
                                        while(!matriz[0][1][1].isCor(Cor.LARANJA) ){//matriz[0][1][1].getKey() != 31){ // enquanto não for laranja
                                                rotacao.E(cubo);
                                                rotacao.D(cubo);
                                        }
                                        setDestino(matriz[0][2][0]);
                                        
                                        rotacao.L_(cubo);
                                        rotacao.U_(cubo);
                                        rotacao.L(cubo);
                                }
                                
                        }
                        
                        //fim da etapa 2
                        //*****************
                        //etapa 3
                        
                        else if( matriz[4][0][0].isCor(Cor.BRANCO) |//(matriz[4][0][0].getKey() >= 45 && matriz[4][0][0].getKey() <= 53) ||
                                        matriz[4][0][2].isCor(Cor.BRANCO) |//(matriz[4][0][2].getKey() >= 45 && matriz[4][0][2].getKey() <= 53) ||
                                        matriz[4][2][0].isCor(Cor.BRANCO) |//(matriz[4][2][0].getKey() >= 45 && matriz[4][2][0].getKey() <= 53) ||
                                        matriz[4][2][2].isCor(Cor.BRANCO) ){//(matriz[4][2][2].getKey() >= 45 && matriz[4][2][2].getKey() <= 53) ){
                                setDestino(matriz[4][2][2]);
                                
                                while(!matriz[4][2][2].isCor(Cor.BRANCO) ){//matriz[4][2][2].getKey() < 45){//enquanto não existir quadrado branco na posi��o [4][2][2]
                                        rotacao.U(cubo);
                                }
                                
                                if(matriz[5][0][2].isCor(Cor.BRANCO) ){//matriz[5][0][2].getKey() >= 45 && matriz[5][0][2].getKey() <= 53){
                                        setDestino(matriz[5][0][2]);
                                        
                                        while(matriz[5][0][2].isCor(Cor.BRANCO) ){//matriz[5][0][2].getKey() >= 45 && matriz[5][0][2].getKey() <= 53){//enquanto existir quadrado branco na posi��o [5][0][2]
                                                rotacao.E(cubo);
                                                rotacao.D(cubo);        
                                        }
                                }
                                
                                setDestino(matriz[0][0][0]);
                                
                                rotacao.R(cubo);
                                rotacao.U(cubo);
                                rotacao.U(cubo);
                                rotacao.R_(cubo);
                        }
                        //fim da etapa 3
                        //**************
                        //etapa 4
                        else if( matriz[0][2][2].isCor(Cor.BRANCO) |//(matriz[0][2][2].getKey() >= 45 && matriz[0][2][2].getKey() <= 53) ||
                                        matriz[1][2][2].isCor(Cor.BRANCO) |//(matriz[1][2][2].getKey() >= 45 && matriz[1][2][2].getKey() <= 53) ||
                                        matriz[2][2][2].isCor(Cor.BRANCO) |//(matriz[2][2][2].getKey() >= 45 && matriz[2][2][2].getKey() <= 53) ||
                                        matriz[3][2][2].isCor(Cor.BRANCO) ) {//(matriz[3][2][2].getKey() >= 45 && matriz[3][2][2].getKey() <= 53) ){
                                setDestino(matriz[0][2][2]);
                                
                                while(!matriz[0][2][2].isCor(Cor.BRANCO) ){//matriz[0][2][2].getKey() < 45){//enquanto não existir quadrado branco na posi��o [0][2][2]
                                        rotacao.Y(cubo);
                                }
                                setDestino(matriz[0][2][2]);
                                
                                rotacao.R(cubo);
                                rotacao.U_(cubo);
                                rotacao.R_(cubo);
                        }
                        
                        //fim da etapa 4
                        //**************
                        //etapa 5
                        else if( matriz[0][2][0].isCor(Cor.BRANCO) |//(matriz[0][2][0].getKey() >= 45 && matriz[0][2][0].getKey() <= 53) ||
                                        matriz[1][2][0].isCor(Cor.BRANCO) |//(matriz[1][2][0].getKey() >= 45 && matriz[1][2][0].getKey() <= 53) ||
                                        matriz[2][2][0].isCor(Cor.BRANCO) |//(matriz[2][2][0].getKey() >= 45 && matriz[2][2][0].getKey() <= 53) ||
                                        matriz[3][2][0].isCor(Cor.BRANCO) ){//(matriz[3][2][0].getKey() >= 45 &&  matriz[3][2][0].getKey() <= 53) ){
                                setDestino(matriz[0][2][0]);
                                
                                while(!matriz[0][2][0].isCor(Cor.BRANCO) ){//matriz[0][2][0].getKey() < 45){//enquanto não existir quadrado branco na posi��o [0][2][0]
                                        rotacao.Y(cubo);
                                }
                                
                                setDestino(matriz[0][2][0]);
                                
                                rotacao.L_(cubo);
                                rotacao.U(cubo);
                                rotacao.L(cubo);
                        }
                        //fim da etapa 5
                        //*****************
                        //etapa 6
                        else{
                                setDestino(matriz[0][2][0]);
                                for(int i = 0; i < 4; i++){
                                        setDestino(matriz[1][0][0]);
                                        if(matriz[0][2][0].isCor(Cor.AZUL) ){//matriz[0][2][0].getKey() <= 8){
                                                if(!matriz[0][1][1].isCor(Cor.AZUL) ){//matriz[0][1][1].getKey() != 4){
                                                        rotacao.L_(cubo);
                                                        rotacao.U_(cubo);
                                                        rotacao.L(cubo);
                                                }
                                        }
                                        else if(matriz[0][2][0].isCor(Cor.VERMELHO) ){//matriz[0][2][0].getKey() >= 9 && matriz[0][2][0].getKey() <= 17){
                                                if(!matriz[0][1][1].isCor(Cor.VERMELHO) ){//matriz[0][1][1].getKey() != 13){
                                                        rotacao.L_(cubo);
                                                        rotacao.U_(cubo);
                                                        rotacao.L(cubo);
                                                }
                                        }
                                        else if(matriz[0][2][0].isCor(Cor.VERDE) ){//matriz[0][2][0].getKey() >= 18 && matriz[0][2][0].getKey() <= 26){
                                                if(!matriz[0][1][1].isCor(Cor.VERDE) ){//matriz[0][1][1].getKey() != 22){
                                                        rotacao.L_(cubo);
                                                        rotacao.U_(cubo);
                                                        rotacao.L(cubo);
                                                }
                                        }
                                        else if(matriz[0][2][0].isCor(Cor.LARANJA) ){//matriz[0][2][0].getKey() >= 27 && matriz[0][2][0].getKey() <= 35){
                                                if(!matriz[0][1][1].isCor(Cor.LARANJA) ){//matriz[0][1][1].getKey() != 31){
                                                        rotacao.L_(cubo);
                                                        rotacao.U_(cubo);
                                                        rotacao.L(cubo);
                                                }
                                        }
                                        rotacao.Y(cubo);
                                }
                        
                        }
                        //fim da etapa 6
                        if(matriz[5][0][0].isCor(Cor.BRANCO) &&//matriz[5][0][0].getKey() >= 45 && 
                                        matriz[5][0][2].isCor(Cor.BRANCO) &&//matriz[5][0][2].getKey() >= 45 && 
                                        matriz[5][2][0].isCor(Cor.BRANCO) &&//matriz[5][2][0].getKey() >= 45 && 
                                        matriz[5][2][2].isCor(Cor.BRANCO) )//matriz[5][2][2].getKey() >= 45)
                                flag = 1;
                }
                return;
        }
        
        /** Método que retorna os movimentos necessários para resolução da etapa Camada do Meio do 
         * Cubo a partir de uma configuração recebida juntamente com a explicação necessária
         */
        public  void resolveCamadaMeio(){
                        resolveCantoInferior();
                    
                        int flag=1, k=0;
                        int cont=0;
                        int flag2=0;
                        int flag3=0;
                        Adesivo[][][] matriz= cubo.getCubo();
                        int x = 0;
                                
                        //TESTE PARA VER SE A CAMADA 2 está PRONTA
                        while(flag!=0){
                                
                                flag=0; 
                                if(/*matriz[0][1][1].isCor(Cor.AZUL)*/matriz[0][1][1].getKey() == 4){ //teste quando a face AZUL está para frente
                                        k=3;
                                        for(int i=0;i<4;i=i+2){         
                                                if((matriz[i][1][0].getKey() != k) ||(matriz[i][1][2].getKey() != k+2)){
                                                        flag=1;
                                                }
                                                k=k+18;
                                        }
                                }

                                if(matriz[0][1][1].getKey() == 13){ //teste quando a face VERMELHA está para frente
                                        k=12;
                                        for(int i=0;i<4;i=i+2){         
                                                if((matriz[i][1][0].getKey() != k)||(matriz[i][1][2].getKey() != k+2)){
                                                        flag=1;
                                                }
                                                k=k+18;
                                        }
                                }


                                if(matriz[0][1][1].getKey() == 22){ //teste quando a face VERDE está para frente
                                        k=21;
                                        for(int i=0;i<4;i=i+2){         
                                                if((matriz[i][1][0].getKey() != k)||(matriz[i][1][2].getKey() != k+2)){
                                                        flag=1;
                                                }
                                                k=k-18;
                                        }
                                }

                                if(matriz[0][1][1].getKey() == 31){ //teste quando a face LARANJA está para frente
                                        k=30;
                                        for(int i=0;i<4;i=i+2){         
                                                if((matriz[i][1][0].getKey() != k)||(matriz[i][1][2].getKey() != k+2)){
                                                        flag=1;
                                                }
                                                k=k-18;
                                        }
                                }
                                //if(flag == 0) camada 2 está pronta
                                //else camada 2 não está pronta

                                //TESTE PARA VER SE TEM AMARELO NOS MEIOS DA CAMADA DE CIMA
                                cont=0;
                                if (flag==1){
                                        
                                                for(int j=0;j<4;j++){
                                                        if(matriz[j][0][1].isCor(Cor.AMARELO)/*matriz[j][0][1].getKey() >= 36 && matriz[j][0][1] <=44*/)
                                                                cont++;
                                                }
                                                if(matriz[4][0][1].isCor(Cor.AMARELO)/*matriz[4][0][1].getKey() >= 36 && matriz[4][0][1] <=44*/)
                                                        cont++;
                                                if(matriz[4][1][0].isCor(Cor.AMARELO)/*matriz[4][1][0].getKey() >= 36 && matriz[4][1][0] <=44*/)
                                                        cont++;
                                                if(matriz[4][1][2].isCor(Cor.AMARELO)/*matriz[4][1][2].getKey() >= 36 && matriz[4][1][2] <=44*/)
                                                        cont++;
                                                if(matriz[4][2][1].isCor(Cor.AMARELO)/*matriz[4][2][1].getKey() >= 36 && matriz[4][2][1] <=44*/)
                                                        cont++;
                                        
                                        //if(cont<4) alguma das pe�as do meio nao tem amarelo
                                        //else todas pe�as do meio possuem amarelo
                                }

                                //FAZENDO A SEGUNDA CAMADA
                                if((cont<4)&&(flag==1)){
                                        flag2=0;
                                        
                                        setDestino(matriz[0][0][1]);
                                        
                                        while(matriz[0][0][1].isCor(Cor.AMARELO) ||/*enquanto for amarelo*/ /*matriz[0][0][1].getKey() >= 36 && matriz[0][0][1] <=44 ||  
                                                        matriz[4][2][1].getKey() >= 36 && matriz[4][2][1] <=44*/
                                                        matriz[4][2][1].isCor(Cor.AMARELO)){
                                                rotacao.U(cubo);
                                        }
                                        
                                        setDestino(matriz[0][0][1]);
                                        
                                        if((/*matriz[0][0][1].isCor(Cor.AZUL)*/matriz[0][0][1].getKey() == 3)||(matriz[0][0][1].getKey() == 5)){//se for azul
                                                
                                                if(!(matriz[0][1][1].isCor(Cor.AZUL)/*matriz[0][1][1].getKey() == 4*/)){
                                                        setDestino(matriz[0][1][1]);
                                                        
                                                        while(!matriz[0][1][1].isCor(Cor.AZUL)/*matriz[0][1][1].getKey() != 4*/){//enquanto não for azul
                                                                rotacao.D(cubo);
                                                                rotacao.E(cubo);
                                                        }
                                                        
                                                }
                                                if(matriz[0][0][1].getKey() == 3)
                                                        flag2=0;
                                                else
                                                        if(matriz[0][0][1].getKey() == 5)
                                                                flag2=1;
                                        }
                                        else{
                                                if(/*matriz[0][0][1].isCor(Cor.VERMELHO)*/(matriz[0][0][1].getKey() == 12)||(matriz[0][0][1].getKey() == 14)){//se for vermelho
                                                        if(!(/*matriz[0][1][1].isCor(Cor.VERMELHO)*/matriz[0][1][1].getKey() == 13)){
                                                                setDestino(matriz[0][1][1]);
                                                                while(/*!matriz[0][1][1].isCor(Cor.VERDE)*/matriz[0][1][1].getKey() != 13){
                                                                        rotacao.D(cubo);
                                                                        rotacao.E(cubo);
                                                                }
                                                        }
                                                        
                                                        if(matriz[0][0][1].getKey() == 12)
                                                                flag2=0;
                                                        else
                                                                if(matriz[0][0][1].getKey() == 14)
                                                                        flag2=1;
                                                }
                                                else{
                                                        if(/*matriz[0][0][1].isCor(Cor.VERDE)*/(matriz[0][0][1].getKey() == 21)||(matriz[0][0][1].getKey() == 23)){
                                                                if(!(/*matriz[0][1][1].isCor(Cor.VERDE)*/matriz[0][1][1].getKey() == 22)){
                                                                        setDestino(matriz[0][1][1]);
                                                                        while(/*!matriz[0][1][1].isCor(Cor.VERDE)*/matriz[0][1][1].getKey() != 22){
                                                                                rotacao.D(cubo);
                                                                                rotacao.E(cubo);
                                                                        }
                                                                }
                                                                if(matriz[0][0][1].getKey() == 21)
                                                                        flag2=0;
                                                                else
                                                                        if(matriz[0][0][1].getKey() == 23)
                                                                                flag2=1;
                                                        }
                                                        else{
                                                                if(/*matriz[0][0][1].isCor(Cor.LARANJA)*/(matriz[0][0][1].getKey() == 30)||(matriz[0][0][1].getKey() == 32)){
                                                                        if(!(matriz[0][1][1].isCor(Cor.LARANJA)/*matriz[0][1][1].getKey() == 31*/)){
                                                                                setDestino(matriz[0][1][1]);
                                                                                while(/*!matriz[0][1][1].isCor(Cor.LARANJA)*/matriz[0][1][1].getKey() != 31){
                                                                                        rotacao.D(cubo);
                                                                                        rotacao.E(cubo);
                                                                                }
                                                                        }
                                                                        if(matriz[0][0][1].getKey() == 30)
                                                                                flag2=0;
                                                                        else
                                                                                if(matriz[0][0][1].getKey() == 32)
                                                                                        flag2=1;
                                                                }
                                                        }
                                                }
                                        }
                                        setDestino(matriz[4][2][1]);
                                        
                                        if(flag2==0){
                                                setDestino(matriz[1][1][1]);
                                                rotacao.U_(cubo);
                                                rotacao.L_(cubo);
                                                rotacao.U_(cubo);
                                                rotacao.L(cubo);
                                                rotacao.U(cubo);
                                                rotacao.Y_(cubo);
                                                rotacao.R(cubo);
                                                rotacao.U(cubo);
                                                rotacao.R_(cubo);
                                        }
                                        else{
                                                if(flag2==1){
                                                        setDestino(matriz[3][1][1]);
                                                        rotacao.U(cubo);
                                                        rotacao.R(cubo);
                                                        rotacao.U(cubo);
                                                        rotacao.R_(cubo);
                                                        rotacao.U_(cubo);
                                                        rotacao.Y(cubo);
                                                        rotacao.L_(cubo);
                                                        rotacao.U_(cubo);
                                                        rotacao.L(cubo);
                                                }
                                        }
                                }
                                else{
                                        //flag3=0;
                                        if((cont==4)&&(flag==1)){
                                                flag3=0;
                                                if(matriz[0][1][1].isCor(Cor.AZUL)/*matriz[0][1][1].getKey() == 4*/){ //verificando pecas erradas na face azul
                                                        k=3;
                                                        setOrigem(matriz[0][1][1]);
                                                        
                                                        for(int i=0;i<4;i=i+2){         
                                                                if((matriz[i][1][0].getKey() != k)||(matriz[i][1][2].getKey() != k+2)){                                                                 
                                                                        
                                                                        if(matriz[i][1][0].getKey() != k && i==0)
                                                                                flag3=1;
                                                                        else
                                                                                if(matriz[i][1][2].getKey() != k+2 && i==0)
                                                                                        flag3=0;
                                                                                else
                                                                                        if(matriz[i][1][0].getKey() != k && i==2){
                                                                                                flag3=1;
                                                                                                
                                                                                                setOrigem(matriz[i][1][0]);
                                                                                                
                                                                                                rotacao.Y(cubo);
                                                                                                rotacao.Y(cubo);
                                                                                        }
                                                                                        else
                                                                                                if(matriz[i][1][2].getKey() != k+2 && i==2){
                                                                                                        flag3=0;
                                                                                                        
                                                                                                        setOrigem(matriz[i][1][0]);
                                                                                                        
                                                                                                        rotacao.Y(cubo);
                                                                                                        rotacao.Y(cubo);
                                                                                                }
                                                                }
                                                                k=k+18;
                                                        }
                                                }

                                                if(matriz[0][1][1].isCor(Cor.VERMELHO)/*matriz[0][1][1].getKey() == 13*/){ //verificando pecas erradas na face vermelha
                                                        k=12;
                                                        setOrigem(matriz[0][1][1]);
                                                        
                                                        for(int i=0;i<4;i=i+2){         
                                                                if((matriz[i][1][0].getKey() != k)||(matriz[i][1][2].getKey() != k+2)){
                                                                        if(matriz[i][1][0].getKey() != k && i==0)
                                                                                flag3=1;
                                                                        else
                                                                                if(matriz[i][1][2].getKey() != k+2 && i==0)
                                                                                        flag3=0;
                                                                                else
                                                                                        if(matriz[i][1][0].getKey() != k && i==2){
                                                                                                flag3=1;
                                                                                                
                                                                                                setOrigem(matriz[i][1][0]);

                                                                                                rotacao.Y(cubo);
                                                                                                rotacao.Y(cubo);
                                                                                        }
                                                                                        else
                                                                                                if(matriz[i][1][2].getKey() != k+2 && i==2){
                                                                                                        flag3=0;
                                                                                                        
                                                                                                        setOrigem(matriz[i][1][0]);

                                                                                                        rotacao.Y(cubo);
                                                                                                        rotacao.Y(cubo);
                                                                                                }
                                                                }
                                                                k=k+18;
                                                        }
                                                }


                                                if(matriz[0][1][1].isCor(Cor.VERDE)/*matriz[0][1][1].getKey() == 22*/){ //verificando pecas erradas na face verde
                                                        k=21;
                                                        setOrigem(matriz[0][1][1]);
                                                        for(int i=0;i<4;i=i+2){         
                                                                if((matriz[i][1][0].getKey() != k)||(matriz[i][1][2].getKey() != k+2)){
                                                                        if(matriz[i][1][0].getKey() != k && i==0)
                                                                                flag3=1;
                                                                        else
                                                                                if(matriz[i][1][2].getKey() != k+2 && i==0)
                                                                                        flag3=0;
                                                                                else
                                                                                        if(matriz[i][1][0].getKey() != k && i==2){
                                                                                                flag3=1;
                                                                                                
                                                                                                setOrigem(matriz[i][1][0]);

                                                                                                rotacao.Y(cubo);
                                                                                                rotacao.Y(cubo);
                                                                                        }
                                                                                        else
                                                                                                if(matriz[i][1][2].getKey() != k+2 && i==2){
                                                                                                        flag3=0;
                                                                                                        
                                                                                                        setOrigem(matriz[i][1][0]);

                                                                                                        rotacao.Y(cubo);
                                                                                                        rotacao.Y(cubo);
                                                                                                }
                                                                }
                                                                k=k-18;
                                                        }
                                                }

                                                if(matriz[0][1][1].getKey() == 31){ //verificando pecas erradas na face laranja
                                                        k=30;
                                                        setOrigem(matriz[0][1][1]);
                                                        for(int i=0;i<4;i=i+2){         
                                                                if((matriz[i][1][0].getKey() != k)||(matriz[i][1][2].getKey() != k+2)){
                                                                        if(matriz[i][1][0].getKey() != k && i==0)
                                                                                flag3=1;
                                                                        else
                                                                                if(matriz[i][1][2].getKey() != k+2 && i==0)
                                                                                        flag3=0;
                                                                                else
                                                                                        if(matriz[i][1][0].getKey() != k && i==2){
                                                                                                flag3=1;
                                                                                                setOrigem(matriz[i][1][0]);

                                                                                                rotacao.Y(cubo);
                                                                                                rotacao.Y(cubo);
                                                                                        }
                                                                                        else
                                                                                                if(matriz[i][1][2].getKey() != k+2 && i==2){
                                                                                                        flag3=0;
                                                                                                        
                                                                                                        setOrigem(matriz[i][1][0]);

                                                                                                        rotacao.Y(cubo);
                                                                                                        rotacao.Y(cubo);
                                                                                                }
                                                                }
                                                                k=k-18;
                                                        }
                                                }
                                        
                                        if(flag3==1){
                                                rotacao.L_(cubo);
                                                rotacao.U_(cubo);
                                                rotacao.L(cubo);
                                                rotacao.U(cubo);
                                                rotacao.Y_(cubo);
                                                rotacao.R(cubo);
                                                rotacao.U(cubo);
                                                rotacao.R_(cubo);
                                        }
                                        else
                                                if(flag3==0){
                                                        
                                                        rotacao.R(cubo);
                                                        rotacao.U(cubo);
                                                        rotacao.R_(cubo);
                                                        rotacao.U_(cubo);
                                                        rotacao.Y(cubo);
                                                        rotacao.L_(cubo);
                                                        rotacao.U_(cubo);
                                                        rotacao.L(cubo);
                                                }
                                                
                                        }
                                }
                        }
                        return;
        }
        
        /** Método que retorna os movimentos necessários para resolução da etapa Cruz Superior do 
         * Cubo à partir de uma configuração recebida juntamente com a explicação necessária
         */
        public void resolveCruzSuperior(){
                resolveCamadaMeio();
                Adesivo[][][] matriz = cubo.getCubo();
                int flag = 0;
                int contAmarelo = 0;
                int x = 0;
                if(matriz[4][0][1].isCor(Cor.AMARELO)/*matriz[4][0][1].getKey() >= 36 && matriz[4][0][1].getKey() <= 44*/) 
                        contAmarelo++;
                
                if(matriz[4][1][0].getKey() >= 36 && matriz[4][1][0].getKey() <= 44)
                        contAmarelo++;
                
                if(matriz[4][1][2].getKey() >= 36 && matriz[4][1][2].getKey() <= 44)
                        contAmarelo++;
                
                if(matriz[4][2][1].getKey() >= 36 && matriz[4][2][1].getKey() <= 44)
                        contAmarelo++;
                setOrigem(matriz[4][0][1]);
                setDestino(matriz[4][1][0]);
                setOrigemDois(matriz[4][1][2]);
                setDestinoDois(matriz[4][2][1]);
                
                if(contAmarelo == 4 ){
                        return;
                        ///flag = 1;
                }
                
                ///while(flag != 1){
                        //etapa 1
                        if(contAmarelo == 0){
                                setOrigem(matriz[4][0][1]);
                                setDestino(matriz[4][2][1]);
                                
                                rotacao.F(cubo);
                                rotacao.U(cubo);
                                rotacao.R(cubo);
                                rotacao.U_(cubo);
                                rotacao.R_(cubo);
                                rotacao.F_(cubo);
                                
                                rotacao.U(cubo);
                                setOrigem(matriz[4][0][1]);
                                setDestino(matriz[4][1][0]);
                                
                                rotacao.F(cubo);
                                rotacao.U(cubo);
                                rotacao.R(cubo);
                                rotacao.U_(cubo);
                                rotacao.R_(cubo);
                                rotacao.F_(cubo);
                                
                                setOrigem(matriz[4][1][2]);
                                setDestino(matriz[4][2][1]);
                                
                                rotacao.F(cubo);
                                rotacao.U(cubo);
                                rotacao.R(cubo);
                                rotacao.U_(cubo);
                                rotacao.R_(cubo);
                                rotacao.F_(cubo);
                        } else{
                                while( !( ( matriz[4][1][0].getKey() >= 36 && matriz[4][1][0].getKey() <= 44 && //enquanto não for amarelo
                                                matriz[4][0][1].getKey() >= 36 && matriz[4][0][1].getKey() <= 44 )  || 
                                                
                                                (matriz[4][1][0].getKey() >= 36 && matriz[4][1][0].getKey() <= 44 && 
                                                 matriz[4][1][2].getKey() >= 36 && matriz[4][1][2].getKey() <= 44)) ) {
                                        
                                        rotacao.U(cubo);
                                }
                                if(matriz[4][0][1].getKey() >= 36 && matriz[4][0][1].getKey() <= 44){
                                        setOrigem(matriz[4][0][1]);
                                        setDestino(matriz[4][1][0]);
                                        
                                        rotacao.F(cubo);
                                        rotacao.U(cubo);
                                        rotacao.R(cubo);
                                        rotacao.U_(cubo);
                                        rotacao.R_(cubo);
                                        rotacao.F_(cubo);
                                }
                                
                                else{
                                        setOrigem(matriz[4][1][2]);
                                        setDestino(matriz[4][1][0]);
                                        
                                        rotacao.F(cubo);
                                        rotacao.U(cubo);
                                        rotacao.R(cubo);
                                        rotacao.U_(cubo);
                                        rotacao.R_(cubo);
                                        rotacao.F_(cubo);
                                        rotacao.F(cubo);
                                        rotacao.U(cubo);
                                        rotacao.R(cubo);
                                        rotacao.U_(cubo);
                                        rotacao.R_(cubo);
                                        rotacao.F_(cubo);
                                }
                        }
                        
                        contAmarelo = 0;
                        
                        if(matriz[4][0][1].getKey() >= 36 && matriz[4][0][1].getKey() <= 44) 
                                contAmarelo++;
                        
                        if(matriz[4][1][0].getKey() >= 36 && matriz[4][1][0].getKey() <= 44)
                                contAmarelo++;
                        
                        if(matriz[4][1][2].getKey() >= 36 && matriz[4][1][2].getKey() <= 44)
                                contAmarelo++;
                        
                        if(matriz[4][2][1].getKey() >= 36 && matriz[4][2][1].getKey() <= 44)
                                contAmarelo++;
                        
                        if(contAmarelo == 4 )
                                flag = 1;
                        
                //}
                        //      cubo.executaSequencia(movs);
//                      for (Iterator iter = movs.iterator(); iter.hasNext();) {
//                              Integer element = (Integer) iter.next();
//                              MovimentoCuboModel.passo(element.intValue());
//                      }
                return;
        }
        
        /** Método que retorna os movimentos necessários para resolução da etapa Face Amarela do 
         * Cubo à partir de uma configuração recebida juntamente com a explicação necessária
         */
        
        public  void resolveFaceAmarela(){
                resolveCruzSuperior();
                
                Adesivo[][][] matriz = cubo.getCubo();
                int flag = 0;
                int contAmarelo = 0;
                int x  =0;
                
                if(matriz[4][0][0].getKey() >= 36 && matriz[4][0][0].getKey() <= 44) 
                        contAmarelo++;
                
                if(matriz[4][0][2].getKey() >= 36 && matriz[4][0][2].getKey() <= 44)
                        contAmarelo++;
                
                if(matriz[4][2][0].getKey() >= 36 && matriz[4][2][0].getKey() <= 44)
                        contAmarelo++;
                
                if(matriz[4][2][2].getKey() >= 36 && matriz[4][2][2].getKey() <= 44)
                        contAmarelo++;
                
                if(contAmarelo == 4 )
                        flag = 1;
                
                while(flag == 0){
                        
                        setDestino(matriz[3][0][2]);
                        
                        //etapa 1
                        if(contAmarelo == 0){
                                
                                while(!matriz[3][0][2].isCor(Cor.AMARELO)/*matriz[3][0][2].getKey() < 36 || matriz[3][0][2].getKey() > 44*/){//enqunto não for amarelo
                                        rotacao.U(cubo);
                                }
                                setOrigem(matriz[4][2][2]);
                                setDestino(matriz[4][0][0]);
                                
                                rotacao.R(cubo);
                                rotacao.U(cubo);
                                rotacao.R_(cubo);
                                rotacao.U(cubo);
                                rotacao.R(cubo);
                                rotacao.U(cubo);
                                rotacao.U(cubo);
                                rotacao.R_(cubo);               
                        }
                        
                        else if (contAmarelo == 2){
                                setDestino(matriz[0][0][0]);
                                
                                while(matriz[0][0][0].getKey() < 36 || matriz[0][0][0].getKey() > 44){
                                        //face amarela while 3
                                        rotacao.U(cubo);
                                }
                                rotacao.R(cubo);
                                rotacao.U(cubo);
                                rotacao.R_(cubo);
                                rotacao.U(cubo);
                                rotacao.R(cubo);
                                rotacao.U(cubo);
                                rotacao.U(cubo);
                                rotacao.R_(cubo);
                        } else {
                                setDestino(matriz[4][2][0]);
                                
                                while(matriz[4][2][0].getKey() < 36 || matriz[4][2][0].getKey() > 44){
                                        rotacao.U(cubo);
                                }
                                
                                rotacao.R(cubo);
                                rotacao.U(cubo);
                                rotacao.R_(cubo);
                                rotacao.U(cubo);
                                rotacao.R(cubo);
                                rotacao.U(cubo);
                                rotacao.U(cubo);
                                rotacao.R_(cubo);
                        }
                        contAmarelo = 0;
                        
                        if(matriz[4][0][0].getKey() >= 36 && matriz[4][0][0].getKey() <= 44) 
                                contAmarelo++;
                        
                        if(matriz[4][0][2].getKey() >= 36 && matriz[4][0][2].getKey() <= 44)
                                contAmarelo++;
                        
                        if(matriz[4][2][0].getKey() >= 36 && matriz[4][2][0].getKey() <= 44)
                                contAmarelo++;
                        
                        if(matriz[4][2][2].getKey() >= 36 && matriz[4][2][2].getKey() <= 44)
                                contAmarelo++;
                        
                        if(contAmarelo == 4 )
                                flag = 1;
                }
                return;
        }
        
        /** Método que retorna os movimentos necessários para resolução da etapa Canto Superior do 
         * Cubo à partir de uma configuração recebida juntamente com a explicação necessária
         */
        public  void resolveCantoSuperior(){
                resolveFaceAmarela();
                
                Adesivo[][][] matriz = cubo.getCubo();
                int flag = 0;
                int x = 0;
                
                if( (matriz[0][0][0].getCor()).equals(matriz[0][0][2].getCor()) &
                                (matriz[1][0][0].getCor()).equals(matriz[1][0][2].getCor()) &
                                (matriz[2][0][0].getCor()).equals(matriz[2][0][2].getCor()) &
                                (matriz[3][0][0].getCor()).equals(matriz[3][0][2].getCor())) {
                        flag = 1;
                }
                
                while( flag != 1 ){
                        //etapa 2 e 3
                        if( (matriz[0][0][0].getCor()).equals(matriz[0][0][2].getCor()) | 
                                        (matriz[1][0][0].getCor()).equals(matriz[1][0][2].getCor()) |
                                        (matriz[2][0][0].getCor()).equals(matriz[2][0][2].getCor()) |
                                        (matriz[3][0][0].getCor()).equals(matriz[3][0][2].getCor())) {
                                
                                setOrigem(matriz[2][0][0]);
                                setDestino(matriz[2][0][2]);
                                
                                while(!matriz[2][0][0].getCor().equals(matriz[2][0][2].getCor())){
                                        rotacao.U(cubo);
                                }
                                rotacao.R_(cubo);
                                rotacao.F(cubo);
                                rotacao.R_(cubo);
                                rotacao.B(cubo);
                                rotacao.B(cubo);
                                rotacao.R(cubo);
                                rotacao.F_(cubo);
                                rotacao.R_(cubo);
                                rotacao.B(cubo);
                                rotacao.B(cubo);
                                rotacao.R(cubo);
                                rotacao.R(cubo);
                        } else{
                                rotacao.R_(cubo);
                                rotacao.F(cubo);
                                rotacao.R_(cubo);
                                rotacao.B(cubo);
                                rotacao.B(cubo);
                                rotacao.R(cubo);
                                rotacao.F_(cubo);
                                rotacao.R_(cubo);
                                rotacao.B(cubo);
                                rotacao.B(cubo);
                                rotacao.R(cubo);
                                rotacao.R(cubo);
                        }
                        
                        if( (matriz[0][0][0].getCor()).equals(matriz[0][0][2].getCor()) & 
                                        (matriz[1][0][0].getCor()).equals(matriz[1][0][2].getCor()) &
                                        (matriz[2][0][0].getCor()).equals(matriz[2][0][2].getCor()) &
                                        ( matriz[3][0][0].getCor()).equals(matriz[3][0][2].getCor())) {
                                flag = 1;
                        }
                }
                return;
        } 
        
        /** Método que retorna os movimentos necessários para resolução da etapa Meio Superior do 
         * Cubo à partir de uma configuração recebida juntamente com a explicação necessária
         */
        public  void resolveMeioSuperior(){ 
                resolveCantoSuperior();
                MainAuxiliar.Gravar(MainAuxiliar.arquivo_passo_anterior, "Cubo antes do último passo:");
                MainAuxiliar.Gravar(MainAuxiliar.arquivo_passo_anterior, cubo);
                
                Adesivo[][][] matriz = cubo.getCubo();
                int x = 0;
                //int flag = 0;
                while(true){
                        setDestino(matriz[0][0][0]);
                        setDestinoDois(matriz[0][0][2]);
                        setOrigem(matriz[0][1][1]);
                        while(!(matriz[0][0][0].getCor().equals(matriz[0][1][1].getCor()))) {
                                rotacao.U(cubo);
                        }
                        if(matriz[0][0][0].getCor().equals(matriz[0][0][1].getCor()) && matriz[0][0][1].getCor().equals(matriz[0][0][2].getCor()) &&
                           matriz[1][0][0].getCor().equals(matriz[1][0][1].getCor()) && matriz[1][0][1].getCor().equals(matriz[1][0][2].getCor()) &
                           matriz[2][0][0].getCor().equals(matriz[2][0][1].getCor()) && matriz[2][0][1].getCor().equals(matriz[2][0][2].getCor()) &
                           matriz[3][0][0].getCor().equals(matriz[3][0][1].getCor()) && matriz[3][0][1].getCor().equals(matriz[3][0][2].getCor()) ){
                                return;
                        } else if(((matriz[0][0][0].getCor()).equals(matriz[0][0][1].getCor()) & matriz[0][0][1].getCor().equals(matriz[0][0][2].getCor())) |
                                          ((matriz[1][0][0].getCor()).equals(matriz[1][0][1].getCor()) & matriz[1][0][1].getCor().equals(matriz[1][0][2].getCor())) | 
                                          ((matriz[2][0][0].getCor()).equals(matriz[2][0][1].getCor()) & matriz[2][0][1].getCor().equals(matriz[2][0][2].getCor())) |
                                          ((matriz[3][0][0].getCor()).equals(matriz[3][0][1].getCor()) & matriz[3][0][1].getCor().equals(matriz[3][0][2].getCor()))){
                                setDestino(matriz[0][0][0]);
                                setDestinoDois(matriz[0][0][2]);
                                
                                setOrigem(matriz[0][1][1]);
                                
                                while(!matriz[2][0][0].getCor().equals(matriz[2][0][1].getCor()) && !matriz[2][0][1].getCor().equals(matriz[2][0][2].getCor())){
                                        rotacao.Y(cubo);
                                }
                                
                                if(matriz[0][0][1].getCor().equals(matriz[3][1][1].getCor())){
                                        setDestino(matriz[0][0][1]);
                                        setOrigem(matriz[3][1][1]);
                                        
                                        rotacao.F(cubo);
                                        rotacao.F(cubo);
                                        rotacao.U(cubo);
                                        rotacao.L(cubo);
                                        rotacao.R_(cubo);
                                        rotacao.F(cubo);
                                        rotacao.F(cubo);
                                        rotacao.L_(cubo);
                                        rotacao.R(cubo);
                                        rotacao.U(cubo);
                                        rotacao.F(cubo);
                                        rotacao.F(cubo);
                                } else if(matriz[0][0][1].getCor().equals(matriz[1][1][1].getCor())){
                                        
                                        rotacao.F(cubo);
                                        rotacao.F(cubo);
                                        rotacao.U_(cubo);
                                        rotacao.L(cubo);
                                        rotacao.R_(cubo);
                                        rotacao.F(cubo);
                                        rotacao.F(cubo);
                                        rotacao.L_(cubo);
                                        rotacao.R(cubo);
                                        rotacao.U_(cubo);
                                        rotacao.F(cubo);
                                        rotacao.F(cubo);
                                        
                                        setDestino(matriz[0][0][1]);
                                        setOrigem(matriz[3][1][1]);
                                }
                        }
                        else {
                                rotacao.F(cubo);
                                rotacao.F(cubo);
                                rotacao.U(cubo);
                                rotacao.L(cubo);
                                rotacao.R_(cubo);
                                rotacao.F(cubo);
                                rotacao.F(cubo);
                                rotacao.L_(cubo);
                                rotacao.R(cubo);
                                rotacao.U(cubo);
                                rotacao.F(cubo);
                                rotacao.F(cubo);
                                setDestino(matriz[0][0][1]);
                                setOrigem(matriz[1][1][1]);
                        }
                        try {
                                Thread.sleep(3000);
                        } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                        }
                }
        }
        
        public void setCubo(CuboMagico3x3x3 cubo) {
                this.cubo = cubo;
        }
        
        public Adesivo getDestino() {
                return destino;
        }

        public void setDestino(Adesivo destino) {
                this.destino = destino;
        }

        public String getMensagem() {
                return mensagem;
        }

        public void setMensagem(String mensagem) {
                this.mensagem = mensagem;
        }

        public Adesivo getOrigem() {
                return origem;
        }

        public void setOrigem(Adesivo origem) {
                this.origem = origem;
        }

        public int getPasso() {
                return passo;
        }

        public void setPasso(int passo) {
                this.passo = passo;
        }

        public Adesivo getOrigemDois() {
                return origemDois;
        }

        public void setOrigemDois(Adesivo origemDois) {
                this.origemDois = origemDois;
        }

        public Adesivo getDestinoDois() {
                return destinoDois;
        }

        public void setDestinoDois(Adesivo destinoDois) {
                this.destinoDois = destinoDois;
        }
        
}